﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SgsUI
{
    [RequireComponent(typeof(RectTransform))]
    public class ViewNode : MonoBehaviour
    { 
        public string id = String.Empty;
        
        public string type;
        public Vector2 anchor_p = new Vector2(0.0f,0.0f);
        public string anchor;
        public Align align;
        public Vector2 pos = new Vector3(0.0f,0.0f);
        public int z = 0;
        public Vector2 size = new Vector2(0.0f,0.0f);
        public float rotation = 0.0f;

        public Vector2 scale = new Vector2(0.0f,0.0f);

        public bool visible = true;

        protected string o_str;

        // private 
        protected RectTransform rect;

        Dictionary<Vector2,string> Anchor_Map = new Dictionary<Vector2,string>
        {
            // left_bottom 默认 可不填写
            {new Vector2(0.0f,1.0f),"left_top"},{new Vector2(0.5f,1.0f),"top"},{new Vector2(1.0f,1.0f),"top_right"},
            {new Vector2(0.0f,0.5f),"left"},{new Vector2(0.5f,0.5f),"center"},{new Vector2(1.0f,0.5f),"right"},
            {new Vector2(0.5f,0.0f),"bottom"},{new Vector2(1.0f,0.0f),"right_bottom"}
        };

        protected ViewNode()
        {
            type = "node";
        }

        public virtual bool HasAtriSize()
        {
            return true;
        }

        public virtual void UpdateParam()
        {
            UpdateRectTransform();
        }

        public void UpdateRectTransform()
        {
            if(rect == null)
                rect = GetComponent<RectTransform>();

            if(!(rect.name == String.Empty || rect.name == GetDefaultName()))
            {
                id = rect.name;
            }
            else
            {
                id = String.Empty;
            }

            pos = new Vector2(rect.anchoredPosition.x,rect.anchoredPosition.y);//,rect.anchoredPosition3D.z);

            z = (int)rect.anchoredPosition3D.z;

            anchor_p = rect.pivot;
            if(Anchor_Map.ContainsKey(anchor_p))
            {
                anchor = Anchor_Map[anchor_p];

                align = new Align
                {
                    anchor = Anchor_Map[anchor_p],
                    x = pos.x,
                    y = pos.y
                };
            }
            else
            {
                anchor = String.Empty;
            }

            size = rect.sizeDelta;

            rotation = -rect.eulerAngles.z;

            scale = rect.localScale;

            visible = gameObject.activeSelf;
        }

        protected virtual string GetDefaultName()
        {
            return "node";
        }

        public virtual void InitViewNode()
        {
            if(rect == null)
                rect = GetComponent<RectTransform>();

            if(rect == null)
                return;

            rect.anchorMax = Vector2.zero;
            rect.anchorMin = Vector2.zero;
            rect.sizeDelta = Vector2.zero;
            rect.pivot = Vector2.zero;
        }

        protected virtual void WriteOtherParam(NodeData nodeData)
        {

        }

        protected void WriteSizeParam(NodeData nodeData)
        {
            if(HasAtriSize())
            {
                ParamData param_size = new ParamData();
                param_size.SetValue("size",size);
                nodeData.AddParam(param_size);
            }
        }

        public void GetParamData(NodeData nodeData)
        {
            ParamData param_type = new ParamData();
            param_type.SetValue("type",type);
            nodeData.AddParam(param_type);

            if(id != String.Empty)
            {
                ParamData param_id = new ParamData();
                param_id.SetValue("id",id);
                nodeData.AddParam(param_id);
            }

            if(anchor != String.Empty && pos != Vector2.zero)
            {
                ParamData param_align = new ParamData();
                param_align.SetValue("align",new Align(){anchor = anchor,x = pos.x,y = pos.y});
                nodeData.AddParam(param_align);
            }
            else if(anchor != String.Empty)
            {
                ParamData param_anchor = new ParamData();
                param_anchor.SetValue("anchor",anchor);
                nodeData.AddParam(param_anchor);
            }
            else if(anchor_p != Vector2.zero)
            {
               // 暂不支持 锚点应该为0.5的倍数
            }
            else
            {
                if(pos != Vector2.zero)
                {
                    ParamData param_pos = new ParamData();
                    param_pos.SetValue("pos",pos);
                    nodeData.AddParam(param_pos);
                }
            }

            WriteSizeParam(nodeData);

            if(z != 0){
                ParamData param_z = new ParamData();
                param_z.SetValue("pos",z);
                nodeData.AddParam(param_z);
            }

            if(rotation != 0.0f)
            {
                ParamData param_rotation = new ParamData();
                param_rotation.SetValue("rotation",(int)rotation);
                nodeData.AddParam(param_rotation);
            }

            if(scale != Vector2.one)
            {
                ParamData param_scale = new ParamData();
                if(scale.x == scale.y)
                {
                    param_scale.SetValue("scale",scale.x);
                }
                else
                {
                    param_scale.SetValue("scale",scale);
                }
                nodeData.AddParam(param_scale);
            }

            if(!visible)
            {
                ParamData param_rotation = new ParamData();
                param_rotation.SetValue("rotation",(int)rotation);
                nodeData.AddParam(param_rotation);
            }

            WriteOtherParam(nodeData);

            Transform t = transform;
            if(t.childCount > 0)
            {
                List<NodeData> node_list = new List<NodeData>();
                ParamData param_children = new ParamData();
                
                for (int i = 0; i < t.childCount; i++)
                {
                    GameObject obj = t.GetChild(i).gameObject;
                    if(obj.TryGetComponent<ViewNode>(out ViewNode viewNode))
                    {
                        NodeData child = new NodeData();
                        viewNode.GetParamData(child);
                        node_list.Add(child);
                    }
                }
                param_children.SetValue("children",node_list);
                nodeData.AddParam(param_children);
            }
        }
    }
}

